<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title> Debounce Demo </title>
    <style>
        body {
            margin: 0;
        }
        .long-scrolling {
            height: 6000px;
            background: -webkit-linear-gradient(0deg, #ff00ff, #00ffff);
            background: -moz-linear-gradient(0deg, #ff00ff, #00ffff);
            background: linear-gradient(0deg, #ff00ff, #00ffff);
        }
        button:nth-child(1) {
            position: fixed;
            top: 50px;
            left: 10px;
        }
        button:nth-child(2) {
            position: fixed;
            top: 80px;
            left: 10px;
        }
        button:nth-child(3) {
            position: fixed;
            top: 110px;
            left: 10px;
        }
        button:nth-child(4) {
            position: fixed;
            top: 140px;
            left: 10px;
        }
    </style>
</head>
<body>
    <div class="long-scrolling">
        <button onclick="normalMode()"> 不优化 </button>
        <button onclick="debounceMode()"> 防抖动优化（Debounce） </button>
        <button onclick="throttleMode()"> 节流优化（Throttle） </button>
        <button onclick="rAFMode()"> use requestAnimationFrame </button>
        <p></p>
    </div>
    <script src="./event-listener.js"></script>
    <script>
        function myAction(event) {
            event && console.log(event.target);
            console.log(window.scrollY);
        }

        function addDebounceListener(target, event, func, wait) {
            function proxyHandle() {
                var timeoutHandle;

                return function scrollAction() {
                    var proxyArgs = arguments;

                    var proxyFunc = function () {
                        func.apply(null, proxyArgs);
                    }

                    clearTimeout(timeoutHandle);
                    timeoutHandle = setTimeout(proxyFunc, wait);
                }
            }

            EventStorage.add(target, event, proxyHandle());
        };

        function addThrottleListener(target, event, func, wait, mustRun) {
            function proxyHandle() {
                var timeoutHandle,
                    startTime = new Date();

                return function scrollAction () {
                    var proxyArgs = arguments,
                        currentTime = new Date();

                    var proxyFunc = function () {
                        func.apply(null, proxyArgs);
                    }

                    clearTimeout(timeoutHandle);
                    if (currentTime - startTime >= mustRun) {
                        func.apply(null, proxyArgs);
                        startTime = currentTime;
                    } else {
                        timeoutHandle = setTimeout(proxyFunc, wait);
                    }
                }
            }

            EventStorage.add(target, event, proxyHandle());
        };


        function addRAFListener(target, event, func) {
            var locking = false;

            function scrollAction() {
                !locking && requestAnimationFrame(execAction);
                !locking && (locking = true);
            }

            function execAction() {
                myAction();
                locking = false;
            }

            EventStorage.add(target, event, scrollAction);
        }

        // --------------------- yes ---------------------- //
        function normalMode() {
            console.warn('switch to normal mode');
            EventStorage.removeAll(window, 'scroll');

            EventStorage.add(window, 'scroll', myAction);
        }

        function debounceMode() {
            console.warn('switch to debounce mode');
            EventStorage.removeAll(window, 'scroll');

            addDebounceListener(window, 'scroll', myAction, 250)
        }

        function throttleMode() {
            console.warn('switch to throttle mode');
            EventStorage.removeAll(window, 'scroll');

            addThrottleListener(window, 'scroll', myAction, 100, 500);
        }
        
        function rAFMode() {
            // requestAnimationFrame
            console.warn('switch to requestAnimationFrame mode');
            EventStorage.removeAll(window, 'scroll');

            addRAFListener(window, 'scroll', myAction);
        }

    </script>
</body>
</html>